//input system handles touchpad and mouse/keyboard controls
//when joypad stuff works well I will implement that as well

//key constants
var KEY;
this.reset_keys = function () {
    KEY = {
        backspace:    8
        ,tab:         9
        ,enter:      13
        ,space:      32
        ,shift:      16
        ,ctrl:       17
        ,alt:	 18
        ,pause:	 19
        ,caps_lock:	 20
        ,escape:	 27
        ,page_up:	 33
        ,page_down:	 34
        ,end:	 35
        ,home:	 36
        ,left:       37
        ,up:	 38
        ,right:      39
        ,down:	 40
        ,insert:	 45
        ,del:	 46
        ,num0:	 48
        ,num1:	 49
        ,num2:	 50
        ,num3:	 51
        ,num4:	 52
        ,num5:	 53
        ,num6:	 54
        ,num7:	 55
        ,num8:	 56
        ,num9:	 57
        ,a:  	 65
        ,b:	         66
        ,c:	         67
        ,d:	         68
        ,e:	         69
        ,f:	         70
        ,g:	         71
        ,h:	         72
        ,i:	         73
        ,j:	         74
        ,k:	         75
        ,l:  	 76
        ,m: 	 77
        ,n: 	 78
        ,o: 	 79
        ,p: 	 80
        ,q: 	 81
        ,r: 	 82
        ,s: 	 83
        ,t: 	 84
        ,u: 	 85
        ,v: 	 86
        ,w: 	 87
        ,x: 	 88
        ,y: 	 89
        ,z: 	 90
        ,mod_left:	 91
        ,mod_right:	 92
        ,select:	 93
        ,numpad0:	 96
        ,numpad1:	 97
        ,numpad2:	 98
        ,numpad3:	 99
        ,numpad4:	 100
        ,numpad5:	 101
        ,numpad6:	 102
        ,numpad7:	 103
        ,numpad8:	 104
        ,numpad9:	 105
        ,multiply:	 106
        ,add:	 107
        ,subtract:	 109
        ,decimal:	 110
        ,divide:	 111
        ,f1:	 112
        ,f2:	 113
        ,f3:	 114
        ,f4:	 115
        ,f5:	 116
        ,f6:	 117
        ,f7:	 118
        ,f8:	 119
        ,f9:	 120
        ,f10:	 121
        ,f11:	 122
        ,f12:	 123
        ,num_lock:	 144
        ,scroll_lock:145
        ,semicolon:	 186
        ,equal:	 187
        ,comma:	 188
        ,dash:	 189
        ,period:	 190
        ,slash_f:    191
        ,grave:	 192
        ,open_b:     219
        ,slash_b:	 220
        ,close_b:	 221
        ,quote:	 222
    };
};

reset_keys(); //reset keys call once when this file loads

var doll = (function(_doll) {
    _doll.input = _doll.input || {};

    //description of the mouse
    _doll.input.mouse_info = function() {
        return {
            x:0, 
            y:0,
            button: 0,
            wheelup: 0,//0,1,or 2 clicks
            wheeldown: 0,
            moveX: 0,//movement amount detected
            moveY: 0
        }
    };

    _doll.input.key_info = function() {
        return {
            code: 0,
            shift: false,
            meta: false,
            ctrl: false,
            x: 0,
            y: 0           
        }
    };

    _doll.input.mouse = new _doll.input.mouse_info();
    _doll.input.key = new _doll.input.key_info();

    //don't change moveX and moveY
    _doll.input.mouse.update = function(info) {
        //[0,0] is screen center -1 left/bottom 1 right/top
        _doll.input.mouse.x = (info.x / _doll.window_width) * 2 - 1;
        _doll.input.mouse.y = -(info.y / _doll.window_height) * 2 + 1;
        _doll.input.mouse.button = info.button;
        _doll.input.mouse.wheelup = info.wheelup;
        _doll.input.mouse.wheeldown = info.wheeldown;
    }


    _doll.input.init = function() {
        var offset = {x: _doll.view.offset().left, y: _doll.view.offset().top};
        
        _doll.input.clicked = new _doll.signals.Signal();
        _doll.input.mousemove = new _doll.signals.Signal();
        _doll.input.mouseup = new _doll.signals.Signal();
        _doll.input.mousedown = new _doll.signals.Signal();
        _doll.input.mouseenter = new _doll.signals.Signal();
        _doll.input.mouseleave = new _doll.signals.Signal();
        _doll.input.keyup = new _doll.signals.Signal();
        _doll.input.keydown = new _doll.signals.Signal();

        //record coordinates on mouse lock
        _doll.input.lockcoords = {x:-1, y:-1};
        _doll.input.lockcenter = {x:-1, y:-1};
        _doll.input.addmousecoords = function(e, info) {
            if(!_doll.input.pointerlocked) {
                info.x = e.pageX - offset.x;
                info.y = e.pageY - offset.y;
                _doll.input.mouse.moveX = 0;
                _doll.input.mouse.moveY = 0;
            }
            else {
                if(_doll.input.lockcoords.x == -1) {
                    _doll.input.lockcoords = {
                        x: e.pageX - offset.x,
                        y: e.pageY - offset.y
                    }
                    _doll.input.lockcenter.x = e.pageX - offset.x;
                    _doll.input.lockcenter.y = e.pageY - offset.y;
                }

                e = e.originalEvent;
                var moveX = e.movementX ||
                    e.mozMovementX ||
                    e.webkitMovementX ||
                    0;
                
                var moveY = e.movementY ||
                    e.mozMovementY ||
                    e.webkitMovementY ||
                    0;

                _doll.input.mouse.moveX += moveX;
                _doll.input.mouse.moveY += moveY;
            }
        }

        _doll.input.onpointerlockchange = function (e) {
            var canvas = _doll.view.get()[0];
            if (_doll.document.pointerLockElement === canvas ||
                _doll.document.mozPointerLockElement === canvas ||
                _doll.document.webkitPointerLockElement === canvas) {
                console.log('Locked Pointer.');
                _doll.input.pointerlocked = true;
            } else {
                _doll.input.lockcoords = {x:-1, y:-1};
                console.log('Unlocked Pointer.');
                _doll.input.pointerlocked = false;
            }
        }

        _doll.input.lockpointer = function () {
            var canvas = _doll.view.get()[0];
            canvas.requestPointerLock = canvas.requestPointerLock ||
                canvas.mozRequestPointerLock ||
                canvas.webkitRequestPointerLock;
        
            canvas.requestPointerLock();
        }

        _doll.view.on('click', function(e) {
            var mouse = new _doll.input.mouse_info();
            e.preventDefault();

            if(!_doll.input.pointerlocked) {
                _doll.input.lockpointer();
            }

            if('which' in e) { //Gecko, Webkit, Opera
                mouse.button = e.which;
            } else if( 'button' in e) { //IE, Opera
                mouse.button = e.button;
            }

            _doll.input.addmousecoords(e,mouse);
            _doll.input.mouse.update(mouse);
            _doll.input.clicked.dispatch(mouse);
        });

        //show our context menu here also handle right click appropiately
        doll.window.oncontextmenu = function (e) {
            var mouse = new _doll.input.mouse_info();
            //they make have used the context menu shortcut to get
            //here as well so check all the buttons again
            //mouse.button3 = true;
            if('which' in e) { //Gecko, Webkit, Opera
                mouse.button = e.which;
            } else if( 'button' in e) { //IE, Opera
                mouse.button = e.button;
            }

            _doll.input.addmousecoords(e,mouse);
            _doll.input.mouse.update(mouse);
            _doll.input.clicked.dispatch(mouse);
            return false;//cancel
        }

        _doll.document.addEventListener('pointerlockchange', _doll.input.onpointerlockchange, false);
        _doll.document.addEventListener('mozpointerlockchange', _doll.input.onpointerlockchange, false);
        _doll.document.addEventListener('webkitpointerlockchange', _doll.input.onpointerlockchange, false);

        //jQuery doesn't handle the following events correctly
        var canvas = _doll.document.getElementById('3d_canvas');

        //cancel
        canvas.ondragstart = function(e) {
            if (e && e.preventDefault) { e.preventDefault(); }
            if (e && e.stopPropagation) { e.stopPropagation(); }
            return false;
        };

        //cancel
        canvas.onselectstart = function(e) {
            if (e && e.preventDefault) { e.preventDefault(); }
            if (e && e.stopPropagation) { e.stopPropagation(); }
            return false;
        };

        //cancel
        _doll.document.body.ontouchstart = function(e) {
            if (e && e.preventDefault) { e.preventDefault(); }
            if (e && e.stopPropagation) { e.stopPropagation(); }
            return false;
        };

        //cancel
        _doll.document.body.ontouchmove = function(e) {
            if (e && e.preventDefault) { e.preventDefault(); }
            if (e && e.stopPropagation) { e.stopPropagation(); }
            return false;
        };

        $(_doll.document).bind('mousewheel DOMMouseScroll', function(e) {
            e.preventDefault();
            e = e.originalEvent;//mouse wheel not supported in jQuery
            var mouse = new _doll.input.mouse_info();
            if('wheelDelta' in e) {//non Firefox
                switch(e.wheelDelta) {
                case 120:
                    mouse.wheelup = 1;
                    break;
                case 240:
                    mouse.wheelup = 2;
                    break;
                case -120:
                    mouse.wheeldown = 1;
                    break;
                case -230:
                    mouse.wheeldown = 2;
                    break;
                default:
                    mouse.wheelup = mouse.wheeldown = 0;
                }
            } else if('detail' in e) {//Firefox
                if(e.detail < 0) {
                    mouse.wheelup = -e.detail;
                    mouse.wheeldown = 0;
                }
                else {
                    mouse.wheeldown = e.detail;
                    mouse.wheelup = 0;
                }
            }

            _doll.input.addmousecoords(e,mouse);
            _doll.input.mouse.update(mouse);
            _doll.input.clicked.dispatch(mouse);
        });

        $(_doll.view).mousedown(function (e) {
            var mouse = new _doll.input.mouse_info();
            _doll.input.addmousecoords(e,mouse);
            mouse.button = e.which;

            _doll.input.mouse.update(mouse);
            _doll.input.mousedown.dispatch(mouse);
        });

        $(_doll.view).mouseup(function (e) {
            var mouse = new _doll.input.mouse_info();
            _doll.input.addmousecoords(e,mouse);
            mouse.button = e.which;

            _doll.input.mouse.update(mouse);
            _doll.input.mouseup.dispatch(mouse);
        });

        $(_doll.view).mouseenter(function (e) {
            var mouse = new _doll.input.mouse_info();
            _doll.input.addmousecoords(e,mouse);
            mouse.button = e.which;

            _doll.input.mouse.update(mouse);
            _doll.input.mouseenter.dispatch(mouse);
        });

        $(_doll.view).mouseleave(function (e) {
            var mouse = new _doll.input.mouse_info();
            _doll.input.addmousecoords(e,mouse);
            mouse.button = e.which;

            _doll.input.mouse.update(mouse);
            _doll.input.mouseleave.dispatch(mouse);
        });

        $(_doll.view).mousemove(function (e) {
            var mouse = new _doll.input.mouse_info();
            _doll.input.addmousecoords(e,mouse);
            mouse.button = e.which;

            _doll.input.mouse.update(mouse);
            _doll.input.mousemove.dispatch(mouse);
        });

        $(_doll.document).keydown(function (e) {
            //doesn't stop browser from closing window on CTRL+W
            e.preventDefault();
            var key = new _doll.input.key_info();
            key.code = e.which;
            key.ctrl = e.ctrlKey;
            key.shift = e.shiftKey;
            key.meta = e.metaKey;
            key.x = _doll.input.mouse.x;
            key.y = _doll.input.mouse.y;

            _doll.input.keydown.dispatch(key);
        });

        $(_doll.document).keyup(function (e) {
            e.preventDefault();
            var key = new _doll.input.key_info();

            key.code = e.which;
            key.ctrl = e.ctrlKey;
            key.shift = e.shiftKey;
            key.meta = e.metaKey;
            key.x = _doll.input.mouse.x;
            key.y = _doll.input.mouse.y;

            _doll.input.keyup.dispatch(key);
        });

    };//end init
    
    _doll.input.on_click = function(listener) {
        _doll.input.clicked.add(listener);
    };

    _doll.input.on_mousemove = function(listener) {
        _doll.input.mousemove.add(listener);
    };

    _doll.input.on_mouseup = function(listener) {
        _doll.input.mouseup.add(listener);
    };

    _doll.input.on_mousedown = function(listener) {
        _doll.input.mousedown.add(listener);
    };

    _doll.input.on_mouseenter = function(listener) {
        _doll.input.mouseenter.add(listener);
    };

    _doll.input.on_mouseleave = function(listener) {
        _doll.input.mouseleave.add(listener);
    };

    _doll.input.on_keydown = function(listener) {
        _doll.input.keydown.add(listener);
    };

    _doll.input.on_keyup = function(listener) {
        _doll.input.keyup.add(listener);
    };

    _doll.input.update = function(delta) {
        _doll.input.mouse.moveX = 0;
        _doll.input.mouse.moveY = 0;
    };
    
    return _doll;
}(doll || {}));
